/** 缓存类型 */
enum CacheType {
  /** 本地缓存 */
  Local,
  /** 会话缓存 */
  Session
}

const cacheKey = {
  /** token令牌 */
  TOKEN: 'TOKEN',
  /** 用户信息 */
  USERINFO: 'USERINFO',
  /** 菜单列表 */
  MENULIST: 'MENULIST',
  /** 是否记住密码 */
  CACHE_IS_REM: 'CACHE_IS_REM',
  /** 用户名 */
  CACHE_NAME: 'CACHE_NAME',
  /** 密码 */
  CACHE_PASSWORD: 'CACHE_PASSWORD',
  /** 主题颜色 */
  THEME_COLOR: 'THEME_COLOR'
} as const

export type CacheKeyType = (typeof cacheKey)[keyof typeof cacheKey]

/**
 * 缓存工具类
 */
class Cache {
  protected storage: Storage
  constructor(type = CacheType.Local) {
    // 根据type设置localStorage或sessionStorage
    this.storage = type === CacheType.Local ? localStorage : sessionStorage
  }

  /**
   * 设置本地缓存；
   * 键名和值作为参数，将会把键值对添加到存储中，如果键名存在，则更新其对应的值。
   * @param key 需要设置的key
   * @param value 需要设置的value
   */
  set(key: CacheKeyType, value: any) {
    // 如果value存在，则将key和value转换为字符串后存储到localStorage中
    this.storage.setItem(key, JSON.stringify(value))
  }

  /**
   * 获取键名对应的值
   * @param key 需要获取的键名key
   * @returns 键名对应的值
   */
  get(key: CacheKeyType) {
    try {
      // 从localStorage中获取key对应的值
      const value = this.storage.getItem(key)
      // 如果value存在，则将value转换为对象后返回
      return value && JSON.parse(value)
    } catch (e) {
      throw new Error('缓存数据解析失败')
    }
  }

  /**
   * 移除本地缓存
   * @param key 需要移除的key
   */
  remove(key: CacheKeyType) {
    // 从localStorage中移除key对应的值
    this.storage.removeItem(key)
  }

  /**
   * 清空存储中的所有键名
   */
  clear() {
    // 清空localStorage中的所有值
    this.storage.clear()
  }

  /**
   * 返回一个整数，表示存储在 Storage 对象中的数据项数量
   */
  get length() {
    return this.storage.length
  }

  /**
   * 返回存储中的第 n 个键名
   * @param n 一个代表从0开始的索引的整数
   * @returns
   */
  key(n = 0) {
    return this.storage.key(n)
  }
}

/** 创建一个本地缓存 */
const localCache = new Cache()
/** 创建一个会话缓存 */
const sessionCache = new Cache(CacheType.Session)
// 导出本地缓存和会话缓存
export { localCache, sessionCache }
